﻿namespace AzureLogProviders.Common
{
    using System;
    using System.Diagnostics;

    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.Diagnostics;
    using Microsoft.WindowsAzure.Diagnostics.Management;
    using Microsoft.WindowsAzure.ServiceRuntime;

    public class Utilities
    {
        public static void SetupLoggingForAzureDiagnosticLogProvider(int scheduledTransferPeriod)
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString");
            SetupLoggingForAzureDiagnosticLogProvider(storageAccount, scheduledTransferPeriod);
            //DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", dmc);
        }

        public static void SetupLoggingForAzureDiagnosticLogProvider(CloudStorageAccount storageAccount, int scheduledTransferPeriod)
        {
            RoleInstanceDiagnosticManager roleInstanceDiagnosticManager = storageAccount.CreateRoleInstanceDiagnosticManager(
                RoleEnvironment.DeploymentId, 
                RoleEnvironment.CurrentRoleInstance.Role.Name, 
                RoleEnvironment.CurrentRoleInstance.Id);

            DiagnosticMonitorConfiguration dmc = roleInstanceDiagnosticManager.GetCurrentConfiguration();
            dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(scheduledTransferPeriod);
            roleInstanceDiagnosticManager.SetCurrentConfiguration(dmc);
            //DiagnosticMonitor.Start(storageAccount, dmc);
        }

        public static void SetupLoggingForEnterpriseRollingFileLogProvider(int scheduledTransferPeriod, string blobContainer)
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString");
            SetupLoggingForEnterpriseRollingFileLogProvider(storageAccount, scheduledTransferPeriod, blobContainer);
        }

        public static void SetupLoggingForEnterpriseRollingFileLogProvider(CloudStorageAccount storageAccount, int scheduledTransferPeriod, string blobContainer)
        {
            RoleInstanceDiagnosticManager roleInstanceDiagnosticManager = storageAccount.CreateRoleInstanceDiagnosticManager(
                RoleEnvironment.DeploymentId,
                RoleEnvironment.CurrentRoleInstance.Role.Name,
                RoleEnvironment.CurrentRoleInstance.Id);

            DiagnosticMonitorConfiguration dmc = roleInstanceDiagnosticManager.GetCurrentConfiguration();
            dmc.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(scheduledTransferPeriod);

            dmc.Directories.DataSources.Add(
                new DirectoryConfiguration
                {
                    Path = RoleEnvironment.GetLocalResource(Constants.Others.LocalResource).RootPath,
                    DirectoryQuotaInMB = RoleEnvironment.GetLocalResource(Constants.Others.LocalResource).MaximumSizeInMegabytes,
                    Container = blobContainer
                });

            roleInstanceDiagnosticManager.SetCurrentConfiguration(dmc);
            //DiagnosticMonitor.Start(storageAccount, dmc);
        }

        //private static DiagnosticMonitorConfiguration GetMonitorConfigurationForDirectory(RoleInstanceDiagnosticManager manager ,int scheduledTransferPeriod)
        //{
        //    DiagnosticMonitorConfiguration dmc = manager.GetCurrentConfiguration();
        //    dmc.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(scheduledTransferPeriod);
        //    return dmc;
        //}

        //private static DiagnosticMonitorConfiguration GetMonitorConfigurationForLogs(RoleInstanceDiagnosticManager manager, int scheduledTransferPeriod)
        //{
        //    DiagnosticMonitorConfiguration dmc = manager.GetCurrentConfiguration();
        //    dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(scheduledTransferPeriod);
        //    return dmc;
        //}

        public static SourceLevels MapSeverityLevelToSourceLevel(LogSeverityLevel severity)
        {
            SourceLevels returnValue = SourceLevels.Information;
            switch (severity)
            {
                case LogSeverityLevel.Debug:
                    returnValue = SourceLevels.Verbose;
                    break;
                case LogSeverityLevel.Error:
                    returnValue = SourceLevels.Error;
                    break;
                case LogSeverityLevel.Fatal:
                    returnValue = SourceLevels.Critical;
                    break;
                case LogSeverityLevel.Informational:
                    returnValue = SourceLevels.Information;
                    break;
                case LogSeverityLevel.Warning:
                    returnValue = SourceLevels.Warning;
                    break;
            }

            return returnValue;
        }

        public static LogSeverityLevel MapSourceLevelToSeverityLevel(SourceLevels severity)
        {
            LogSeverityLevel returnValue = LogSeverityLevel.Informational;
            switch (severity)
            {
                case SourceLevels.Verbose:
                    returnValue = LogSeverityLevel.Debug;
                    break;
                case SourceLevels.Error:
                    returnValue = LogSeverityLevel.Error;
                    break;
                case SourceLevels.Critical:
                    returnValue = LogSeverityLevel.Fatal;
                    break;
                case SourceLevels.Information:
                    returnValue = LogSeverityLevel.Informational;
                    break;
                case SourceLevels.Warning:
                    returnValue = LogSeverityLevel.Warning;
                    break;
            }

            return returnValue;
        }

        /// <summary>
        /// Maps the type of the severity level to event log.
        /// </summary>
        /// <param name="severity">The severity.</param>
        /// <returns>The trace event type</returns>
        public static TraceEventType MapSeverityLevelToEventLogType(LogSeverityLevel severity)
        {
            TraceEventType returnValue = TraceEventType.Information;

            switch (severity)
            {
                case LogSeverityLevel.Debug:
                    returnValue = TraceEventType.Verbose;
                    break;
                case LogSeverityLevel.Error:
                    returnValue = TraceEventType.Error;
                    break;
                case LogSeverityLevel.Fatal:
                    returnValue = TraceEventType.Critical;
                    break;
                case LogSeverityLevel.Informational:
                    returnValue = TraceEventType.Information;
                    break;
                case LogSeverityLevel.Warning:
                    returnValue = TraceEventType.Warning;
                    break;
            }

            return returnValue;
        }

        public static Guid GetActivityId()
        {
            return Trace.CorrelationManager.ActivityId;
        }

        public static Guid SetActivityId(Guid activityId)
        {
            return Trace.CorrelationManager.ActivityId = activityId;
        }

        public static void StartLogicalOperation(string operation)
        {
            Trace.CorrelationManager.StartLogicalOperation(operation);
        }

        public static void StopLogicalOperation()
        {
            Trace.CorrelationManager.StopLogicalOperation();
        }
    }
}
